﻿using System;
using System.Collections.Generic;

using SobrietyEngine.Common;
using SobrietyEngine.Components;
using SobrietyEngine.Scene;
using SobrietyEngine.Logging;

using Microsoft.Xna.Framework;

namespace SobrietyEngine.Actor.Builders
{
    /// <summary>
    /// This builder creates an instance of a defined actor type that was
    /// loaded into the actor library from a cfg file
    /// </summary>
    public class ActorDefinition: BaseActorBuilder
    {
        String type;
        ActorTemplate actorDefinition;

        public ActorDefinition(ActorTemplate actorDef)
        {
            type = actorDef.Name;
            actorDefinition = actorDef;
        }

        override public IActor Build(IScene scene, Vector3 position, Vector3 direction, Parameters parameters)
        {
            IActor temp = scene.CreateEmptyActor();

            //if we have an args defined
            if (parameters != null)
            {
                throw new NotImplementedException();
            }

            //create all the components
            foreach (String comp in actorDefinition.Components.Keys)
            {
                SobrietyEngine.Components.IComponent cmp;
                cmp = ComponentFactory.Build(comp);
                temp.AttachComponent(cmp);

                try
                {
                    //no need to call set if no parameters
                    if (actorDefinition.Components[comp].Params.Count != 0)
                        cmp.Set(actorDefinition.Components[comp]);
                }
                catch (Exception ex)
                {
                    Logger.Error("ComponentFactory:: error in Set(). likely not implemented on " + cmp.GetType().ToString() + "\n" + ex.Message);
                }
            }

            //initialize the actor
            temp.Initialize();

            //set our instance pos and orientation
            IPosition pos = temp.Get<IPosition>();
            if (pos != null)
                pos.PositionV3 = position;

            IOrientation or = temp.Get<IOrientation>();
            if (or != null)
                or.Set(direction);

            //return the instance
            return temp;
        }

        /*
        public IActor Build(IScene scene, ActorTemplate instance)
        {
            IActor temp = scene.CreateEmptyActor();

            //if we have an args defined
            if (instance != null)
            {
                //we need to merge the actorDefinition with the passed in isntance,
                //overwriting values in the actorDefinition that already exist
                ActorTemplate merged = new ActorTemplate();

                //copy compnent params from actorDefinition
                foreach (String compName in actorDefinition.Components.Keys)
                    merged.Components[compName] = new Parameters(actorDefinition.Components[compName]);

                //go through all component params in args
                foreach (String compName in instance.Components.Keys)
                {
                    //merge params together if they arleady exist
                    if (merged.Components.ContainsKey(compName))
                    {
                        merged.Components[compName] = merged.Components[compName].Merge(instance.Components[compName], true);
                    }
                    //just move over the args stuff
                    else
                        merged.Components[compName] = instance.Components[compName];
                }

                //set the tempalte to be this new merged actorDefinition, then construct away
                actorDefinition = merged;
            }

            //create all the components
            foreach (String comp in actorDefinition.Components.Keys)
            {
                SobrietyEngine.Components.IComponent cmp;
                cmp = ComponentFactory.Build(comp);
                temp.AttachComponent(cmp);

                try
                {
                    //check to make sure we ID the args correctly
                    //iuf we have an args and theid comp, set its value
                    if (instance != null)
                    {
                        if (instance.Name != String.Empty)
                        {
                            if (cmp.GetType() == typeof(IId))
                                ((IId)cmp).Id = instance.Name;
                        }
                    }

                    //no need to call set if no parameters
                    if (actorDefinition.Components[comp].Params.Count != 0)
                        cmp.Set(actorDefinition.Components[comp]);
                }
                catch (Exception ex)
                {
                    Logger.Error("ComponentFactory:: error in Set(). likely not implemented on " + cmp.GetType().ToString() + "\n" + ex.Message);
                }
            }

            //check to make sure we ID the args correctly
            //check for names. if we have n args, and no id comp, create and attach it
            if (instance != null)
            {
                if (instance.Name != String.Empty)
                {
                    IId id = temp.Get<IId>();
                    if (id == null)
                        temp.AttachComponent(new Components.Common.IdCmp(instance.Name));
                }
            }

            return temp;
        }
         * */

        override public String GetAlias()
        {
            return type;
        }

        override public String GetTypeString()
        {
            return type;
        }
    }
}